package cn.sh.library.mgts.sparql.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import cn.sh.library.mgts.base.Pinyin4j;
import cn.sh.library.mgts.base.Pinyin4j.Type;
import cn.sh.library.mgts.base.ResponseCodeEnums;
import cn.sh.library.mgts.common.Constant;
import cn.sh.library.mgts.framework.exception.CustomRuntimeException;
import cn.sh.library.mgts.sparql.ConstructQuery;
import cn.sh.library.mgts.sparql.ConstructSparql;
import cn.sh.library.mgts.sparql.JpWorkSparql;
import cn.sh.library.mgts.sparql.Namespace;
import cn.sh.library.mgts.sparql.SparqlExecution;

@Service
public class JpWorkSparqlImpl implements JpWorkSparql {

	@Autowired
	ConstructSparql constructsparql;

	@Value("${endpoint.jp}")
	private String endpoint;

	@Value("${endpoint.mgts}")
	private String ep;

	private static Logger logger = LoggerFactory.getLogger(JpWorkSparqlImpl.class);
	private static Logger loggerSync = LoggerFactory.getLogger(Constant.LOGGER_SYNC);
	private static Logger loggerSyncErr = LoggerFactory.getLogger(Constant.LOGGER_SYNCERR);

//	final String filePathTmp = "C:\\TempFiles\\es\\mgts_tmp\\";
	final String filePathTmp = "D:\\generatefiles\\es\\20200922mgts\\mgts_tmp\\";

	public static List<String> insts = new ArrayList<>();
	public static List<String> works = new ArrayList<>();

	@Override
	public boolean syncIndex(String uri) {
		if (StringUtils.isBlank(uri)) {
			throw new CustomRuntimeException(ResponseCodeEnums.PARAMS_ERROR, "参数为空！");
		}
		try {
			String checkItemSparql = Namespace.getNsPrefixString()
					+ " select ?item where{?s a bf:Work. ?inst a bf:Instance; bf:instanceOf ?s. ?item a bf:Item; bf:itemOf ?inst .filter (?s = <"
					+ uri + ">)} limit 1";
			ArrayList list = SparqlExecution.vQuery(endpoint, checkItemSparql, new String[] { "item" });
			String constructSparql = list.size() > 0 ? ConstructQuery.CONSTRUCT_JP_WORKS.toString(uri)
					: ConstructQuery.CONSTRUCT_JP_WORKS_WITHOUT_ITEM.toString(uri);
			String jsonld = constructsparql.construnct(endpoint, constructSparql);
//			boolean isindex = commonService.insertOrUpdateDoc(uri, jsonld, Constant.JP_WORK_INDEX, Constant.JP_DEFAULT_TYPE);
//			if(isindex) {
//				loggerSync.info(uri);	
//			}else {
//				throw new CustomRuntimeException();
//			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			loggerSyncErr.info(uri);
			e.printStackTrace();
			throw new CustomRuntimeException(ResponseCodeEnums.DATABASE_ERROR);
		}
		return true;
	}

	@Override
	@Async("asyncServiceExecutor") // 异步
	public void instcont(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String ss = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_CONTRIBUTION_INS.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
				FileUtils.writeStringToFile(new File(filePathTmp + "instcontri\\" + i + ".json"), ss, "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}

	@Override
	@Async("asyncServiceExecutor") // 异步
	public void instcontPny(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String ss = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_CONTRIBUTION_INS.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
				// ss转json 取personName-value 转pny构造map塞入
				JsonObject jsonObj = new JsonParser().parse(ss).getAsJsonObject();
				if (jsonObj.get("contribution").isJsonObject()) {
					String chsName = null;
					if (jsonObj.get("contribution").getAsJsonObject().get("personName").isJsonObject()) {
						chsName = jsonObj.get("contribution").getAsJsonObject().get("personName").getAsJsonObject()
								.get("@value").getAsString();

					} else {
						// 红色文献下载机构内多个名字的 只取其一
						chsName = jsonObj.get("contribution").getAsJsonObject().get("personName").getAsJsonArray()
								.get(0).getAsJsonObject().get("@value").getAsString();
					}
					// 转拼音
					Pinyin4j py = new Pinyin4j();
					String pnyName = py.toPinYinAll(chsName, "", Type.LOWERCASE);
					JsonObject pny = new JsonObject();
					pny.addProperty("@language", "pny");
					pny.addProperty("@value", pnyName);
					jsonObj.get("contribution").getAsJsonObject().add("personNamePny", pny);
				} else {
					JsonArray arr = new JsonArray();
					String chsName = null;
					for (JsonElement element : jsonObj.get("contribution").getAsJsonArray()) {
						jsonObj.remove("contribution");
						if (element.getAsJsonObject().get("personName").isJsonObject()) {
							chsName = element.getAsJsonObject().get("personName").getAsJsonObject().get("@value")
									.getAsString();
						} else {
							chsName = element.getAsJsonObject().get("personName").getAsJsonArray().get(0)
									.getAsJsonObject().get("@value").getAsString();
						}
//						String chsName = element.getAsJsonObject().get("personName").getAsJsonObject().get("@value")
//								.getAsString();
						// 转拼音
						Pinyin4j py = new Pinyin4j();
						String pnyName = py.toPinYinAll(chsName, "", Type.LOWERCASE);
						JsonObject pny = new JsonObject();
						pny.addProperty("@language", "pny");
						pny.addProperty("@value", pnyName);
						element.getAsJsonObject().add("personNamePny", pny);
						arr.add(element);
					}
					jsonObj.add("contribution", arr);
				}
				FileUtils.writeStringToFile(new File(filePathTmp + "instcontriPny\\" + i + ".json"),
						jsonObj.toString() + "\r\n", "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}
	
	@Override
	@Async("asyncServiceExecutor") // 异步
	public void insTitlePny(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String titlePnyString = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_TITLE_PNY.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
				// titlePnyString转json 取personName-value 转pny构造map塞入
				JsonObject jsonObj = new JsonParser().parse(titlePnyString).getAsJsonObject();
				String titlePny = jsonObj.get("title").getAsJsonObject().get("label").getAsJsonObject()
						.get("@value").getAsString();
				// 转拼音
				Pinyin4j py = new Pinyin4j();
				String pnyTitle = py.toPinYinAll(titlePny, "", Type.LOWERCASE);
				
				JsonObject pny = new JsonObject();
				pny.addProperty("@language", "zh-pny");
				pny.addProperty("@value", pnyTitle);
				jsonObj.get("title").getAsJsonObject().add("labelPny", pny);
				FileUtils.writeStringToFile(new File(filePathTmp + "instTitlePny\\" + i + ".json"),jsonObj.toString() + "\r\n", "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}
	
	@Override
	@Async("asyncServiceExecutor") // 异步
	public void insProAndPub(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String proandPubString = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_PROANDPUB.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
				JsonObject jsonObj = new JsonParser().parse(proandPubString).getAsJsonObject();
				FileUtils.writeStringToFile(new File(filePathTmp + "instProAndPub\\" + i + ".json"),jsonObj.toString() + "\r\n", "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
		
	}
	
	@Override
	@Async("asyncServiceExecutor") // 异步
	public void instParaTitle(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String ss = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_TITLE.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
//				System.out.println(ss.length());
				if(ss.length()!=145) {
					FileUtils.writeStringToFile(new File(filePathTmp + "instTitle\\" + i + ".json"), ss, "UTF-8", true);
				}
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}
	
	@Override
	@Async("asyncServiceExecutor") // 异步
	public void instResEdiPro(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String ss = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_RESEDIPRO_INS.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
//				System.out.println(ss.length());
				if(ss.length()!=145) {
					FileUtils.writeStringToFile(new File(filePathTmp + "instResEdiPro\\" + i + ".json"), ss, "UTF-8", true);
				}
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}
	
	@Override
	@Async("asyncServiceExecutor")
	public void insIdentiTermPlaceLabe(int i){
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String ss = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_INSBUCHONG.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
//				System.out.println(ss.length());
				if(ss.length()!=145) {
					FileUtils.writeStringToFile(new File(filePathTmp + "insIdentiTermPlaceLabe\\" + i + ".json"), ss, "UTF-8", true);
				}
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}

	@Override
	@Async("asyncServiceExecutor") // 异步
	public void workcont(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= works.size()) {
				break;
			}
			String uri = works.get(j);
			try {
				String ss = constructsparql.construnct(ep,
						ConstructQuery.CONSTRUCT_MGTS_CONTRIBUTION_WORK.toString(uri),
						"{\"@context\":{\"@vocab\":\"http://www.library.sh.cn/\"},\"@omitGraph\":true,\"@type\":\"Work\",\"item\":{\"@type\":\"Item\"}}");
				FileUtils.writeStringToFile(new File(filePathTmp + "workcontri\\" + i + ".json"), ss, "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}

	@Override
	@Async("asyncServiceExecutor") // 异步
	public void workLang(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= works.size()) {
				break;
			}

			String uri = works.get(j);
			try {
				String ss = constructsparql.construnct(ep,
						ConstructQuery.CONSTRUCT_MGTS_WORKLANG.toString(uri),
						"{\"@context\":{\"@vocab\":\"http://www.library.sh.cn/\"},\"@omitGraph\":true,\"@type\":\"Work\",\"item\":{\"@type\":\"Item\"}}");
				FileUtils.writeStringToFile(new File(filePathTmp + "workLang\\" + i + ".json"), ss, "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
	}

	@Override
	@Async("asyncServiceExecutor") // 异步
	public void insClassProtion(int i) {
		for (int j = i * 500; j < (i + 1) * 500; j++) {
			if (j >= insts.size()) {
				break;
			}

			String uri = insts.get(j);
			try {
				String proandPubString = constructsparql.construnct(ep, ConstructQuery.CONSTRUCT_MGTS_INS_CLASSPORTION.toString(uri),
						Constant.CONSTRUCT_MGTS_FRAME);
				JsonObject jsonObj = new JsonParser().parse(proandPubString).getAsJsonObject();
				FileUtils.writeStringToFile(new File(filePathTmp + "instClassPortion\\" + i + ".json"),jsonObj.toString() + "\r\n", "UTF-8", true);
			} catch (Exception e) {
				loggerSyncErr.info(uri);
				e.printStackTrace();
			}
		}
		
	}


}
